package org.example.brave.spring.webmvc;

import org.example.brave.http.HttpTracing;
import org.example.brave.servlet.TracingFilter;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.*;
import java.io.IOException;

/**
 * Similar to {@link TracingFilter}, except that it initializes from Spring.
 *
 * <p> {@link org.springframework.web.filter.DelegatingFilterProxy} is similar, but it uses
 * volatile references as it allows lazy initialization from doGet. This filter cannot do that
 * anyway because {@code ServletRequest.getServletContext()} was added after servlet 2.5!
 */
public final class DelegatingTracingFilter implements Filter {

    Filter delegate; // servlet ensures create is directly followed by init, so no need for volatile

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        Filter tracingFilter = delegate;
        if (tracingFilter == null) { // don't break on initialization error.
            chain.doFilter(request, response);
        } else {
            tracingFilter.doFilter(request, response, chain);
        }
    }

    @Override public void init(FilterConfig filterConfig) {
        ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(filterConfig.getServletContext());
        HttpTracing httpTracing = WebMvcRuntime.get().httpTracing(ctx);
        delegate = TracingFilter.create(httpTracing);
    }

    @Override public void destroy() {
        // TracingFilter is stateless, so nothing to destroy
    }
}
